//
//  YSIAPManager.swift

import UIKit
import StoreKit
import AppTrackingTransparency
import AdSupport
import ProgressHUD

/** 共享密钥 */
let kSecretKey = "76b7ca57ed9a4c6c9f238ccbd34c64a0"
/** 凭证校验地址 */
let KSandboxReceiptCheckUrl = "https://sandbox.itunes.apple.com/verifyReceipt"
let KReceiptCheckUrl = "https://buy.itunes.apple.com/verifyReceipt"
/** 订阅状态检验地址 */
let KStateCheckUrl = ""
/** 连续订阅id */
let KContinuityID = "yumo_lianxubaonianhuiyuan"
let KPermanentContinuityID = "yumo_yongjiu"
var KCurrentSubscribeID = KContinuityID

/// 订阅日期
let originalPurchaseDateIdentifier = "originalPurchaseDate"
/// 过期日期
let expiresDateIdentifier = "expiresDate"

class YSIAPManager: NSObject {
    
    private static var manager: YSIAPManager?
    // 交易是否结束
    private var isRequestFinished: Bool?
    // 判断是购买还是恢复
    private var isRestore: Bool?
    // 当前购买的商品信息
    var product:SKProduct?

    class func shared() -> YSIAPManager {
        struct Manager {
            static let manager = YSIAPManager()
        }
        return Manager.manager
    }
    
    private override init() {
        super.init()
        SKPaymentQueue.default().add(self)
        isRequestFinished = true
    }
    
    deinit {
        SKPaymentQueue.default().remove(self)
    }
}

extension YSIAPManager {
    // 请求商品列表
    public func requestProduct(_ productId: String) {
        KCurrentSubscribeID = productId
        isRestore = false
        if isRequestFinished == true {
            if SKPaymentQueue.canMakePayments() { // 用户允许app内购
                if !productId.isEmpty {
                    ProgressHUD.show()
                    isRequestFinished = false; //正在请求
                    let product = [productId]
                    let productSet = NSSet(array: product)
                    let productsRequest = SKProductsRequest(productIdentifiers: productSet as! Set<String>)
                    productsRequest.delegate = self
                    productsRequest.start()
                }
            }else { //没有权限
                print("没有购买权限！")
                isRequestFinished = true
            }
        }else {
            print("上次请求购买未完成，请稍后重试！")
        }
    }
    
    // 恢复购买
    func restore() {
        ProgressHUD.show()
        self.isRestore = true
        isRequestFinished = false;
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    
    // 交易完成
    private func handlePurchased(_ transaction: SKPaymentTransaction) {
        guard transaction.transactionState == .purchased else { return }
        print("交易完成！")
        if let originalTransaction = transaction.original {
            // 如果是自动续费的订单,originalTransaction会有内容
            if let transactionIdentifier = originalTransaction.transactionIdentifier {
                print("自动续费的订单ID = \(transactionIdentifier)")
            }
        } else {
            // 普通购买，以及第一次购买自动订阅
            if let transactionIdentifier = transaction.transactionIdentifier {
                print("普通购买，以及第一次购买自动订阅ID = \(transactionIdentifier)")
            }
        }
        verifyReceipt()
        completeTransaction(transaction)
    }

    // 交易失败
    private func handleFailed(_ transaction: SKPaymentTransaction) {
        ProgressHUD.dismiss()
        guard transaction.transactionState == .failed else { return }
        print("交易失败！")
        if let error = transaction.error as NSError? {
            if error.code != SKError.paymentCancelled.rawValue {
                // 处理其他类型的错误
                print("Transaction failed with error: \(error.localizedDescription)")
            } else {
                print("Transaction was cancelled")
            }
        }
        completeTransaction(transaction)
        
    }
    
    // 恢复购买
    private func handleRestored(_ transaction: SKPaymentTransaction) {
        guard transaction.transactionState == .restored else { return }
        print("恢复购买！")
        verifyReceipt()
        completeTransaction(transaction)
    }

    
    // 配置交易状态
    private func completeTransaction(_ transaction: SKPaymentTransaction) {
        isRequestFinished = true; // 请求完成
        SKPaymentQueue.default().finishTransaction(transaction)
    }
    
    // 根据公司需求校验凭证
    public func verifyReceipt() {
        print("购买完成，正在校验购买凭证...")
        let receiptURL = Bundle.main.appStoreReceiptURL
        if let receiptPath = receiptURL?.path, FileManager.default.fileExists(atPath: receiptPath) {
            verifyReceipt { [self] in
                print("校验成功！")
                DispatchQueue.main.async {
                    if isTopViewController(ZSSubscriptionViewController.self) {
                        if let vc =  UIApplication.topViewController() as? ZSSubscriptionViewController {
                            NotificationCenter.default.post(name: NSNotification.Name("ZSSubscriptionReloadData"), object: nil)
                            if let _ = vc.presentingViewController {
                                vc.dismiss(animated: true)
                            } else if let _ = vc.navigationController {
                                vc.navigationController?.popViewController(animated: true)
                            }
                        }
                    }
                }
                if let product = self.product {
                    setSKUInfo(product)
                }
            } failure: {
                print("校验失败！")
            }
        } else {
            // 如果凭证为空，则再发一次凭证请求
            let refreshReceiptRequest = SKReceiptRefreshRequest(receiptProperties: [:])
            refreshReceiptRequest.delegate = self
            refreshReceiptRequest.start()
        }
    }
    
    // 获取凭证
    func getReceipt() -> String? {
        guard let receiptURL = Bundle.main.appStoreReceiptURL else {
            return nil
        }
        guard let receiptData = try? Data(contentsOf: receiptURL) else {
            return nil
        }
        let encodeReceiptStr = receiptData.base64EncodedString(options: .endLineWithLineFeed)
        return encodeReceiptStr
    }
    
    // 校验凭证
    private func verifyReceipt(success: @escaping () -> Void, failure: @escaping () -> Void) {
        guard let receipt = getReceipt() else {
            return
        }
        verifyReceiptRequest(receipt: receipt) {
            success()
        } failure: {
            self.verifySandboxReceiptRequest(receipt: receipt) {
                success()
            } failure: {
                failure()
            }
        }
    }
    
    // 检验订单是否还在订阅期内
    func checkOrderState(success: @escaping () -> Void, failure: @escaping () -> Void) {
        guard let receipt = getReceipt() else {
            return
        }
        verifyReceiptRequest(receipt: receipt) {
            print("订单还在有效期内")
            success()
        } failure: {
            self.verifySandboxReceiptRequest(receipt: receipt) {
                print("订单还在有效期内")
                success()
            } failure: {
                print("订单已失效")
                UserDefaults.standard.setValue("", forKey: "orderId")
                failure()
            }

        }
    }
    
    private func verifyReceiptRequest(receipt: String, success: @escaping () -> Void, failure: @escaping () -> Void) {
        do {
            let requestData = ["receipt-data": receipt, "password": kSecretKey]
            let requestDataJson = try JSONSerialization.data(withJSONObject: requestData, options: [])
            let url = URL(string: KReceiptCheckUrl)!
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.httpBody = requestDataJson
            
            let task = URLSession.shared.dataTask(with: request) { [self] (data, response, error) in
                ProgressHUD.dismiss()
                if let error = error {
                    print("Error: \(error.localizedDescription)")
                    failure()
                    return
                }
                if let data = data,
                   let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                   let status = json["status"] as? Int {
                    if status == 0 {
                        handleValidReceipt(json: json) {
                            success()
                        } failure: {
                            failure()
                        }
                        return
                    } else if let status = json["status"] as? Int, status == 21007 {
                        failure()
                    }else {
                        failure()
                    }
                }
            }
            task.resume()
        } catch {
            print("验证购买过程中发生错误，错误信息: \(error.localizedDescription)")
            failure()
        }
    }
    
    private func verifySandboxReceiptRequest(receipt: String, success: @escaping () -> Void, failure: @escaping () -> Void) {
        do {
            let requestData = ["receipt-data": receipt, "password": kSecretKey]
            let requestDataJson = try JSONSerialization.data(withJSONObject: requestData, options: [])
            let url = URL(string: KSandboxReceiptCheckUrl)!
            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.httpBody = requestDataJson
            
            let task = URLSession.shared.dataTask(with: request) { [self] (data, response, error) in
                ProgressHUD.dismiss()
                if let error = error {
                    print("Error: \(error.localizedDescription)")
                    failure()
                    return
                }
                
                if let data = data,
                   let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                   let status = json["status"] as? Int {
                    if status == 0 {
                        handleValidReceipt(json: json) {
                            success()
                        } failure: {
                            failure()
                        }
                        return
                    }
                    failure()
                }
            }
            task.resume()
        } catch {
            print("验证购买过程中发生错误，错误信息: \(error.localizedDescription)")
            failure()
        }
    }
    
    private func handleValidReceipt(json: [String: Any], success: @escaping () -> Void, failure: @escaping () -> Void) {
        // 处理连续订阅部分
        if let latestReceiptInfo = json["latest_receipt_info"] as? [[String: Any]] {
            let purchases = latestReceiptInfo.filter({ $0["product_id"] as? String == KCurrentSubscribeID })
            if let purchase = purchases.max(by: {
                guard let timestamp1 = $0["expires_date_ms"] as? String,
                      let timestamp2 = $1["expires_date_ms"] as? String,
                      let time1 = Double(timestamp1),
                      let time2 = Double(timestamp2)
                else { return false }
                return time1 < time2
            }) {
                if let originalPurchaseDateMS = purchase["original_purchase_date_ms"] as? String,
                   let expiresDateMS = purchase["expires_date_ms"] as? String,
                   let originalTransactionId = purchase["original_transaction_id"] as? String {
                    let originalPurchaseDate = Date(timeIntervalSince1970: TimeInterval(originalPurchaseDateMS)! / 1000)
                    let expiresDate = Date(timeIntervalSince1970: TimeInterval(expiresDateMS)! / 1000)
                    let isSubscriptionActive = expiresDate > Date()
                    if isSubscriptionActive {
                        saveOrderId(orderId: originalTransactionId)
                        UserDefaults.standard.setValue(originalPurchaseDate, forKey: originalPurchaseDateIdentifier)
                        UserDefaults.standard.setValue(expiresDate, forKey: expiresDateIdentifier)
                        success()
                        return
                    }
                }
            }
        }
        
        // 处理永久购买部分
        if let receipt = json["receipt"] as? [String: Any],
           let inAppPurchases = receipt["in_app"] as? [[String: Any]] {
            let permanentPurchases = inAppPurchases.filter { purchase in
                if let productId = purchase["product_id"] as? String,
                   productId == KCurrentSubscribeID,
                   purchase["expires_date_ms"] == nil {
                    return true
                }
                return false
            }
            
            if !permanentPurchases.isEmpty {
                if let originalTransactionId = permanentPurchases.first?["original_transaction_id"] as? String {
                    saveOrderId(orderId: originalTransactionId)
                    if let originalPurchaseDateMS = permanentPurchases.first?["original_purchase_date_ms"] as? String {
                        let originalPurchaseDate = Date(timeIntervalSince1970: TimeInterval(originalPurchaseDateMS)! / 1000)
                        UserDefaults.standard.setValue(originalPurchaseDate, forKey: originalPurchaseDateIdentifier)
                    }
                    UserDefaults.standard.setValue("永久会员", forKey: expiresDateIdentifier)
                    success()
                    return
                }
            }
        }
        
        failure()
    }

    // 保存订单ID
    func saveOrderId(orderId: String) {
        let defaults = UserDefaults.standard
        defaults.setValue(orderId, forKey: "orderId")
        defaults.synchronize()
    }

    // 获取订单ID
    func getOrderId() -> String? {
        let defaults = UserDefaults.standard
        return defaults.string(forKey: "orderId")
    }

    // 购买商品埋点
    func setSKUInfo(_ product:SKProduct) {
        let urlString = baseUrl + "/lbbmajiabao/api/maidian"
        let url = URL(string: urlString)!
        guard let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String else { return }
        guard let udid = UIDevice.current.identifierForVendor?.uuidString else { return }
        let parameters: [String: Any] = ["name": appName, "price": product.price, "udid": udid as Any]
        let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = jsonData
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                return
            }
            guard let data = data else {
                return
            }

            do {
                if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                   let dict = json["data"] as? [String: Any] {
                    print("\(dict)")
                    self.product = nil
                }
                
            } catch {
                print("Error parsing JSON: \(error)")
            }
        }

        task.resume()
    }
    
}

extension YSIAPManager: SKProductsRequestDelegate {
    // 获取商品列表
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        if products.count == 0 {
            isRequestFinished = true
            return
        }
        if response.invalidProductIdentifiers.count > 0 {
            print("商品请求错误,error:%@", response.invalidProductIdentifiers);
        }
        print("商品详情:%@", products[0].description);
        print("商品价格:%@", products[0].price);
        print("商品名字:%@", products[0].productIdentifier);
        self.product = products[0]
        // 请求购买
        let payment: SKPayment = SKPayment(product: products.first!)
        SKPaymentQueue.default().add(payment)
    }
}

extension YSIAPManager: SKPaymentTransactionObserver {
    
    // 当交易状态发生变化时调用。在这个方法中，你可以处理购买成功、购买失败、恢复购买等不同状态的交易。
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for tran in transactions {
            switch tran.transactionState {
            case .purchasing: // 正在交易
                print("正在交易中.......")
                break
            case .purchased: // 交易完成
                handlePurchased(tran)
                break
            case .failed: // 交易失败
                handleFailed(tran)
                break
            case .restored: // 恢复购买
                handleRestored(tran)
                break
            default:
                completeTransaction(tran)
                break
            }
        }
    }
    
    // 当交易被从队列中移除时调用。你可以在这里执行任何必要的清理工作。
    func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
        
    }

    // 恢复购买失败时调用。你可以在这里处理恢复购买失败的情况。
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
        
    }

    // 恢复购买完成时调用。在这里可以执行与恢复购买相关的任何收尾工作。
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        if queue.transactions.count > 0 {
            for tran in queue.transactions {
                if let transactionIdentifier = tran.original?.transactionIdentifier {
                    completeTransaction(tran)
                    break
                }
            }
        } else { // 没有可恢复的购买项
            ProgressHUD.dismiss()
            print("没有可恢复的购买项！")
            
        }
    }

    // 在向用户显示应用内购买确认界面之前调用。你可以在这里处理是否允许用户购买商品。
    func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
        return true
    }
}

extension YSIAPManager: SKRequestDelegate {
    func requestDidFinish(_ request: SKRequest) {
        if let request = request as? SKReceiptRefreshRequest {
            let receiptURL = Bundle.main.appStoreReceiptURL
            if let path = receiptURL?.path, FileManager.default.fileExists(atPath: path) {
                verifyReceipt {
                    print("再次请求凭证后，校验成功！")
                } failure: {
                    print("再次请求凭证后，校验失败！")
                }
            }
        }
    }
}


